package com.topisv.tms.service.stock.outstorage;

import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.lang.StringUtils;
import org.hibernate.ejb.criteria.predicate.ComparisonPredicate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.topisv.tms.entity.AreaGroup;
import com.topisv.tms.entity.Customers;
import com.topisv.tms.entity.User;
import com.topisv.tms.entity.stock.CusStock;
import com.topisv.tms.entity.stock.instorage.OutstorageInfo;
import com.topisv.tms.entity.stock.oustorage.OutstorageBill;
import com.topisv.tms.entity.stock.oustorage.OutstorageBillItem;
import com.topisv.tms.entity.stock.oustorage.OutstoragePickTask;
import com.topisv.tms.entity.stock.oustorage.OutstorageSendTask;
import com.topisv.tms.repository.AreaGroupDao;
import com.topisv.tms.repository.CustomersDao;
import com.topisv.tms.repository.UserDao;
import com.topisv.tms.repository.stock.CusStockDao;
import com.topisv.tms.repository.stock.instorage.OutstorageInfoDao;
import com.topisv.tms.repository.stock.outstorage.OutstorageBillDao;
import com.topisv.tms.repository.stock.outstorage.OutstorageBillItemDao;
import com.topisv.tms.repository.stock.outstorage.OutstoragePickTaskDao;
import com.topisv.tms.repository.stock.outstorage.OutstorageSendTaskDao;
import com.topisv.tms.utils.rule.TMSTransportRule;

/**
 * 出库拣货任务_service
 * @author ch
 *
 */
@Component
@Transactional(readOnly = true)
public class OutstoragePickTaskService {
	
	@Autowired
	private OutstoragePickTaskDao outstoragePickTaskDao;
	@Autowired
	private CustomersDao customersDao;
	@Autowired
	private AreaGroupDao areaGroupDao;
	@Autowired
	private UserDao userDao;
	@Autowired
	private OutstorageBillDao outstoragebilldao;
	@Autowired
	private OutstorageBillItemDao outstorageBillItemDao;
	@Autowired
	private CusStockDao cusStockDao;
	@Autowired
	private OutstorageSendTaskDao outstorageSendTaskDao;
	@Autowired
	private OutstorageInfoDao outstorageInfoDao;
	/**
	 * 查找任务
	 * @param param 查询参数
	 * @return
	 */
	public List<OutstoragePickTask> loadTaskByParam(Map<String, Object> param) {
		Specification<OutstoragePickTask> spec = getWhereClause(param);
		List<OutstoragePickTask> workTaskList = this.outstoragePickTaskDao.findAll(spec);
		for (OutstoragePickTask t: workTaskList){
			this.setDetail(t);
		}
		return workTaskList;
	}
	
	/**
	 * 设置属性明细
	 * @param workOrder 
	 */
	private void setDetail(OutstoragePickTask task){
		//customer
		String customerCode=task.getCustomerCode();
		Customers customer=this.customersDao.findByCustomerCode(customerCode);
		task.setCustomer(customer);
		
		//warehouse
		String warehouseCode=task.getWarehouseCode();
		AreaGroup warehouse=this.areaGroupDao.findByGroupCode(warehouseCode);
		task.setWarehouse(warehouse);
		
		//worker
	    String workerUuid=task.getWorkerUuid();
	    User worker=this.userDao.findByJobuuid(workerUuid);
	    task.setWorker(worker);
	    
	    //bill
	    String billCode=task.getBillCode();
	    OutstorageBill bill=this.outstoragebilldao.loadByBillCode(billCode);
	    task.setBill(bill);
	    
	    
	}
	
	/**
	 * 查询条件封装
	 * @param param
	 * @return
	 */
	private Specification<OutstoragePickTask> getWhereClause(final Map<String, Object> param) {
		return new Specification<OutstoragePickTask>(){
			@Override
		    public Predicate toPredicate(Root<OutstoragePickTask> r, CriteriaQuery<?> q, CriteriaBuilder cb) {
		      Predicate pre = cb.conjunction();
		      
		      //customerCodes
		      String customerCodes=(String) param.get("customerCodes");
		      if(StringUtils.isNotBlank(customerCodes)) {
		    	  String[] customerCodeSplit = customerCodes.split(":");
				  ComparisonPredicate[] tempCustomerCode = new ComparisonPredicate[customerCodeSplit.length];
				  int i = 0;
				  for (String _customerCode : customerCodeSplit) {
					 tempCustomerCode[i] = (ComparisonPredicate) cb.equal(r.get("customerCode"), _customerCode);
					 i++;
				  }
				  pre.getExpressions().add(cb.or(tempCustomerCode));
		      }
			  
		      //areagroups
		      String areagroups=(String) param.get("areagroups");
		      if(StringUtils.isNotBlank(areagroups)) {
		    	  String[] areagroupSplit = areagroups.split(":");
				  ComparisonPredicate[] areagroupArray = new ComparisonPredicate[areagroupSplit.length];
				  int j = 0;
				  for (String _areagroup : areagroupSplit) {
						areagroupArray[j] = (ComparisonPredicate) cb.equal(r.get("warehouseCode"), _areagroup);
						j++;
				  }
				  pre.getExpressions().add(cb.or(areagroupArray));
			  }
		      
		      Date fromDate= (Date) param.get("fromDate");
		      if (fromDate != null) {
		        pre.getExpressions().add(cb.greaterThanOrEqualTo(r.<Date>get("createTime"), fromDate));
		      }
		      
		      Date toDate= (Date) param.get("toDate");
		      if (toDate != null) {
		        pre.getExpressions().add(cb.lessThanOrEqualTo(r.<Date>get("createTime"), toDate));
		      }
		      
		      String status=(String) param.get("status"); 
		      if(StringUtils.isNotBlank(status)){
		    	  if(status.equals("myTask")){ //我的拣货任务
		    		  pre.getExpressions().add(cb.or(
		    				  cb.equal(r.get("status"),"token"),
		    				  cb.equal(r.get("status"),"doing")
		    				  ));
		    	  }
		    	  else{
		    		  pre.getExpressions().add(cb.equal(r.get("status"),status)); 
		    	  }
			  }
		      
		      String workerUuid=(String) param.get("workerUuid");
		      if(StringUtils.isNotBlank(workerUuid)){
					pre.getExpressions().add(cb.equal(r.get("workerUuid"),workerUuid));
			  }	
		      
		      return pre;
		    }
		  };
       }
	
	/**
	 * 领取任务
	 * @param taskId 任务ID
	 * @param userId 任务执行人
	 * @param taskType 任务类型 （ pick:拣货  lampPick:灯光拣选   pkg:包装    send:发货 ）
	 * @throws Exception 
	 */
	@Transactional(readOnly = false,rollbackFor=Exception.class)
	public void takeTask(Long taskId, String jobuuid) throws Exception{
		
		try {
			
			//修改拣货任务状态
			OutstoragePickTask task=this.outstoragePickTaskDao.findOne(taskId);
			task.setWorkerUuid(jobuuid);
			task.setStatus("token"); 
			this.outstoragePickTaskDao.save(task);
			
			
			//修改出库单状态
			OutstorageBill bill=this.outstoragebilldao.loadByBillCode(task.getBillCode());
			bill.setStatus("2"); //状态 （1.创建出库单 2.领取拣货任务 3. 拣货完成 4.出库 5.收货确认 )
			this.outstoragebilldao.save(bill);
		
		} catch (Exception e) {
			throw e;
		}
		
	}

	/**
	 * 查询
	 * @param taskId
	 * @return
	 */
	public OutstoragePickTask loadTaskById(Long taskId) {
		OutstoragePickTask task=this.outstoragePickTaskDao.findOne(taskId);
		this.setDetail(task);
		return task;
	}

	/**
	 * 完成拣货任务
	 * @param taskId
	 * @throws Exception 
	 */
	@Transactional(readOnly = false,rollbackFor=Exception.class)
	public void completeTask(Long taskId) throws Exception {
		try {
			
			Date now=new Date();
			
			//修改拣货任务状态
			OutstoragePickTask task=this.outstoragePickTaskDao.findOne(taskId);
			task.setStatus("finish");
			this.outstoragePickTaskDao.save(task);
			
			//修改出库单状态
			OutstorageBill bill=this.outstoragebilldao.loadByBillCode(task.getBillCode());
			bill.setStatus("3"); //状态 （1.创建出库单 2.领取拣货任务 3. 拣货完成 4.出库 5.收货确认 )
			this.outstoragebilldao.save(bill);
			
			//修改库存数据
			List<OutstorageBillItem> itemList=this.outstorageBillItemDao.loadByBillCode(bill.getBillCode());
			for (OutstorageBillItem item : itemList) {
				String customerCode=item.getCustomerCode();
				String warehouseCode=item.getWarehouseCode();
				String stockCode=item.getStockCode();
				String boxCode=item.getBoxCode();
				String sku=item.getSku();
				Integer num=item.getNum();
				
				CusStock stock=this.cusStockDao.loadStock(customerCode, warehouseCode, stockCode, boxCode, sku);
				if(stock==null){
					throw new Exception("库存异常");
				}
				if(stock.getTransportNum() - num < 0){//add by LiBin 20160808
                    throw new Exception("调拨占用库存异常：stockCode:"+stockCode+" sku:" + sku);
                }
				stock.setTransportNum(stock.getTransportNum()-num);
				this.cusStockDao.save(stock);
				
				OutstorageInfo oi = new OutstorageInfo();
				oi.setCustomerCode(customerCode);
				oi.setWarehouseCode(warehouseCode);
				oi.setBatchCode(null);
				oi.setTaskCode(null);
				oi.setSku(sku);
				oi.setNum(num);
				oi.setOpeTime(new Date());
				oi.setBillType(bill.getBillType());
				oi.setAboutCode(bill.getBillCode());
				outstorageInfoDao.save(oi);
			}
			
			
			//创建发货任务
			OutstorageSendTask sendTask=new OutstorageSendTask();
			sendTask.setBillCode(bill.getBillCode());
			sendTask.setCreateTime(now);
			sendTask.setStatus("undo");
			sendTask.setTaskCode(TMSTransportRule.generateOutSendTaskCode());
			sendTask.setWarehouseCode(bill.getWarehouseOutCode());
			sendTask.setCustomerCode(bill.getCustomerCode());
			this.outstorageSendTaskDao.save(sendTask);
			
			
			
		} catch (Exception e) {
			throw e;
		}
	}


}
